﻿using BLL;
using CefSharp;
using CefSharp.DevTools.Emulation;
using CefSharp.WinForms;
using HslCommunication;
using HslCommunication.Profinet.Panasonic;
using Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
//using static MachineStatusClient.Form2;

namespace MachineStatusClient
{
    public partial class Form3 : Form
    {
        private System.Windows.Forms.Timer timer1;
        BContentToSqlServer bts = new BContentToSqlServer();
        private XFUserControl _sourceControl;
        // 班次时间存储
        private TimeSpan dayShiftStart;
        private TimeSpan dayShiftEnd;
        private TimeSpan nightShiftStart;
        private TimeSpan nightShiftEnd;

        //private bool isInitialized = false;
        //// PLC通信对象
        //private PanasonicMewtocolOverTcp plcClient;
        ////private string plcIp = "192.168.150.11"  \\192.168.10.197\drawing;
        //private string plcIp = "192.168.2.110";
        //private int plcPort = 1025;
        //// 添加类成员变量
        private bool isFirstStatusUpdate = true;
        // 添加设备状态监控相关成员变量
        private System.Windows.Forms.Timer statusTimer;
        private enum DeviceStatus { Running, Alarm, Stop, Error }
        private enum ShiftType { DayShift, NightShift }

        // 时间累计
        private TimeSpan runningTime = TimeSpan.Zero;
        private TimeSpan alarmTime = TimeSpan.Zero;
        private TimeSpan stopTime = TimeSpan.Zero;
        private TimeSpan currentStatusStartTime = TimeSpan.Zero;
        private DateTime lastStatusChangeTime = DateTime.Now;
        // 状态和班次
        private DeviceStatus currentStatus;
        private ShiftType currentShift /*= ShiftType.Unknown*/;
        private ShiftType previousShift /*= ShiftType.Unknown*/;
        private DateTime shiftChangeTime = DateTime.MinValue;

        // PLC通信对象
        private PanasonicMewtocolOverTcp plcClient;
        private string MachindNo = ConfigurationManager.AppSettings["MachineId"];
        private string EsopInitialDirectory = ConfigurationManager.AppSettings["EsopInitialDirectory"];
        private string plcIp = ConfigurationManager.AppSettings["PlcIp"];
        private int plcPort = int.Parse(ConfigurationManager.AppSettings["PlcPort"]);

        // 点位地址
        private string statusAddress = "";
        private string totalCountAddress = "";
        private string okCountAddress = "";
        private string ngCountAddress = "";

        // 生产数据
        private int totalCount = 0;
        private int okCount = 0;
        private int ngCount = 0;

        // 计时器
        private Stopwatch unifiedStopwatch = new Stopwatch();
        private DateTime lastStatusChange = DateTime.Now;
        private bool isInitialized = false;

        //private DoubleBufferedTableLayoutPanel topPanel;

        private System.Windows.Forms.Timer idleTimer;
        private const int IdleTimeout = 2 * 60 * 1000; // 5分钟（毫秒）

        // 在Form3类中添加成员变量
        private System.Windows.Forms.Timer refreshTimer;
        // 添加常量定义
        private const int WM_QUERYENDSESSION = 0x11;
        private const int WM_ENDSESSION = 0x16;

        //// 添加网络共享根路径字段
        //private string networkShareRoot;
        private DJUserControl userControl;
        private HRUserControl hrUserControl;
        private TimerUserControl timerUserControl;
        private ESOPUserControl esopUserControl;
        private XFUserControl  xfUserControl;
        private string machineId;

        private System.Windows.Forms.Timer checkRecordTimer;
        private bool hasDayCheckRecord = true;
        private bool isCheckTimerRunning = false;
        private volatile bool isPlcConnected = false;
        public Form3()
        {
            InitializeComponent();
            Initialize();

            // 添加应用程序域和进程退出事件处理
            AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            tabControl1.DrawItem += TabControl1_DrawItem;
            tabControl1.SelectedIndexChanged += (s, e) => tabControl1.Invalidate();
            // 添加以下代码 ↓
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                if (args.Name.StartsWith("CefSharp.Core.Runtime"))
                {
                    string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CefSharp.Core.Runtime.dll");
                    return File.Exists(path) ? Assembly.LoadFrom(path) : null;
                }
                return null;
            };
            InitializeCefSharp();
            dataGridView1.CellDoubleClick += DataGridView1_CellDoubleClick;
            // 添加以下两行
            this.MouseClick += Form3_MouseClick;
            this.ControlAdded += Form3_ControlAdded;
            //InitializeUI();
            //InitializePdfViewer();
            // 设置窗体启动时为全屏
            this.WindowState = FormWindowState.Maximized;

            // 初始化PLC客户端
            plcClient = new PanasonicMewtocolOverTcp(plcIp, plcPort);

            // 启用双缓冲
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                         ControlStyles.AllPaintingInWmPaint |
                         ControlStyles.UserPaint, true);
            this.UpdateStyles();

            // 为关键控件启用双缓冲
            //EnableDoubleBuffering(lblCurrentStatusDuration);
            //EnableDoubleBuffering(lblStatus);

            // 初始化状态计时器
            statusTimer = new System.Windows.Forms.Timer();
            statusTimer.Interval = 1000; // 1秒触发一次
            statusTimer.Tick += StatusTimer_Tick;

            // 初始化空闲计时器
            idleTimer = new System.Windows.Forms.Timer();
            idleTimer.Interval = IdleTimeout;
            idleTimer.Tick += IdleTimer_Tick;
            // 初始化刷新定时器
            refreshTimer = new System.Windows.Forms.Timer();
            refreshTimer.Interval = 30 * 60 * 1000; // 30分钟
            refreshTimer.Tick += RefreshTimer_Tick;

            // 初始化点检记录检查定时器
            //checkRecordTimer = new System.Windows.Forms.Timer();
            //checkRecordTimer.Interval = 1 * 60 * 1000; // 5分钟
            //checkRecordTimer.Tick += CheckRecordTimer_Tick;
            // 获取网络共享根路径
            //networkShareRoot = GetNetworkShareRoot(EsopInitialDirectory);
        }

        private void TabControl1_DrawItem(object sender, DrawItemEventArgs e)
        {
            TabControl tabControl = sender as TabControl;
            TabPage tabPage = tabControl.TabPages[e.Index];
            Rectangle tabRect = tabControl.GetTabRect(e.Index);
            bool isSelected = tabControl.SelectedIndex == e.Index;

            // 绘制背景
            using (Brush backBrush = new SolidBrush(Color.LightGray))
            {
                e.Graphics.FillRectangle(backBrush, e.Bounds);
            }

            // 绘制边框
            Color borderColor = isSelected ? Color.Blue : Color.Black;
            using (Pen borderPen = new Pen(borderColor, 2))
            {
                e.Graphics.DrawRectangle(borderPen, tabRect);
            }

            // 绘制文本
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            using (Brush textBrush = new SolidBrush(tabPage.ForeColor))
            {
                e.Graphics.DrawString(tabPage.Text, tabPage.Font, textBrush, tabRect, sf);
            }
        }
        private void DataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            // 忽略标题行和无效点击
            if (e.RowIndex < 0 || e.ColumnIndex < 0) return;
            // 获取料号值
            string workno = dataGridView1.Rows[e.RowIndex].Cells["Column2"].Value?.ToString();
            machineId = workno;
            if (!string.IsNullOrEmpty(workno))
            {
                // 跳转到新窗体
                OpenAddForm();
            }
            else
            {
                MessageBox.Show("料号为空，无法查询");
            }

        }

        #region 系统关机
        // 重写 WndProc 方法处理 Windows 消息
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_QUERYENDSESSION:
                    // 系统正在询问是否可以结束会话（关机）
                    SaveDataOnShutdown();
                    m.Result = (IntPtr)1; // 允许关机
                    break;

                case WM_ENDSESSION:
                    // 系统正在结束会话（实际关机）
                    if (m.WParam != IntPtr.Zero) // 非零表示正在关机
                    {
                        SaveDataOnShutdown();
                    }
                    m.Result = IntPtr.Zero;
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        // 专门用于关机时保存数据的方法
        private void SaveDataOnShutdown()
        {
            if (isDataSavedOnShutdown) return; // 避免重复保存
            isDataSavedOnShutdown = true;

            try
            {
                string shiftType = previousShift.ToString();
                MachineStatusMessage data = new MachineStatusMessage
                {
                    MachineId = MachindNo,
                    RunningTime = FormatTimeSpan(runningTime),
                    AlarmTime = FormatTimeSpan(alarmTime),
                    StopTime = FormatTimeSpan(stopTime),
                    AlarmMessage = "系统关机",
                    //TeamGroup = !string.IsNullOrEmpty(shiftType)
                    //    ? GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType))
                    //    : GetShiftDisplayName(currentShift),
                    TeamGroup = GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType)),
                    OkQty = okCount,
                    NgQty = ngCount,
                    GetTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };

                // 使用同步方式保存，避免异步操作在关机时被中断
                bts.InsertMachineStatusTime(data);
            }
            catch (Exception ex)
            {
                // 可以尝试将错误记录到文件，但注意关机时文件操作可能失败
                try
                {
                    File.WriteAllText("shutdown_error.log", $"{DateTime.Now}: {ex.Message}");
                }
                catch
                {
                    // 忽略所有错误
                }
            }
        }

        // 添加一个标志防止重复保存
        private bool isDataSavedOnShutdown = false;

        private void CurrentDomain_ProcessExit(object sender, EventArgs e)
        {
            SaveDataOnShutdown();
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            SaveDataOnShutdown();
        }

        #endregion
        /// <summary>
        /// 工单明细展示
        /// </summary>
        private void OpenAddForm()
        {
            // 1. 创建承载窗体
            Form hostForm = new Form();
            hostForm.Text = "工单详情";  // 设置窗体标题
            hostForm.Size = new Size(1650, 650);
            hostForm.StartPosition = FormStartPosition.CenterScreen;  // 关键居中设置

            // 2. 实例化用户控件
            DJAddUserControl dJAddUserControl = new DJAddUserControl();

            // 3. 传递工单号到用户控件（需在DJAddUserControl中添加接收方法）
            dJAddUserControl.SetMachineId(machineId);

            // 4. 设置用户控件填充窗体
            dJAddUserControl.Dock = DockStyle.Fill;

            // 5. 将控件添加到窗体
            hostForm.Controls.Add(dJAddUserControl);

            // 6. 显示窗体
            //hostForm.Show();
            hostForm.ShowDialog(this);
            //DJAddUserControl dJAddUserControl = new DJAddUserControl();
            //dJAddUserControl.Show();
        }
        /// <summary>
        /// 用户控件的绑定
        /// </summary>
        public void Initialize()
        {
            userControl = new DJUserControl();
            hrUserControl = new HRUserControl();
            timerUserControl = new TimerUserControl();
            esopUserControl = new ESOPUserControl();
            xfUserControl = new XFUserControl();
            xfUserControl.Dock = DockStyle.Fill;
            tabControl1.TabPages[3].Controls.Add(userControl);
            hrUserControl.Dock = DockStyle.Fill;
            tabControl1.TabPages[4].Controls.Add(hrUserControl);
            timerUserControl.Dock = DockStyle.Fill;
            tabControl1.TabPages[5].Controls.Add(timerUserControl);
            esopUserControl.Dock = DockStyle.Fill;
            tabControl1.TabPages[2].Controls.Add(esopUserControl);

            tabControl1.TabPages[6].Controls.Add(xfUserControl);

            // 订阅关键数据更新事件
            xfUserControl.CriticalDataUpdated += XfUserControl_CriticalDataUpdated;
        }
        private int D1;//状态
        private int D2;//Ok计数
        private int D3;//Ng计数
        // 事件处理程序
        private void XfUserControl_CriticalDataUpdated(string deviceId, int d1, int d2, int d3)
        {
            // 确保在UI线程上更新控件
            if (InvokeRequired)
            {
                Invoke(new Action<string, int, int, int>(XfUserControl_CriticalDataUpdated),
                      deviceId, d1, d2, d3);
                return;
            }

            // 更新关键数据显示
             D1 = d1;
             D2 = d2;
             D3 = d3;

            //// 记录最后更新时间
            //lblLastUpdate.Text = $"最后更新: {DateTime.Now:HH:mm:ss}";
        }
        private void InitializeCefSharp()
        {
            if (!Cef.IsInitialized.HasValue)
            {
                var settings = new CefSettings();

                // 设置自定义缓存路径
                settings.RootCachePath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                    "MachineStatusClient_CefCache"
                );
                // 确保目录存在
                try
                {
                    Directory.CreateDirectory(settings.RootCachePath);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"创建缓存目录失败: {ex.Message}");
                }

                // 完全禁用日志记录
                settings.LogSeverity = LogSeverity.Disable;

                Cef.Initialize(settings);
            }
        }
        /// <summary>
        /// 定时跳转第一个tabpage1页
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void IdleTimer_Tick(object sender, EventArgs e)
        {
            //// 如果当前不在TabPage1，则切换回去
            //if (tabControl1.SelectedTab != tabPage1)
            //{
            //    tabControl1.SelectedTab = tabPage1;
            //}
            // 检查是否有打开的模态窗体（如新增点检记录）
            bool hasOpenModalForm = Application.OpenForms.Cast<Form>()
                .Any(form => form != this && form.Modal);

            // 检查是否在非设备运行状态页
            bool isNotOnStatusPage = tabControl1.SelectedTab != tabPage1;

            // 满足以下条件时才跳转回设备运行状态页:
            // 1. 当前不在设备运行状态页
            // 2. 没有打开的模态窗体
            if (isNotOnStatusPage && !hasOpenModalForm)
            {
                tabControl1.SelectedTab = tabPage1;
            }

            // 重置计时器（重新开始计时）
            idleTimer.Stop();
            idleTimer.Start();
        }

        // 添加定时器事件处理方法,定时刷新工单查询
        private void RefreshTimer_Tick(object sender, EventArgs e)
        {
            // 确保在UI线程上执行刷新操作
            if (this.InvokeRequired)
            {
                this.Invoke(new Action(() => BindWorkOrdersToDataGridView(MachindNo)));
            }
            else
            {
                BindWorkOrdersToDataGridView(MachindNo);
            }
        }

       

        private void Form3_Load(object sender, EventArgs e)
        {
            // 读取设备编码并显示到文本框
            textBoxMac.Text = MachindNo;
            BindWorkOrdersToDataGridView(textBoxMac.Text);

            // 初始化状态标签页布局
            InitializeStatusTabLayout();

            // 加载点位配置
            LoadDeviceAddresses();

            // 加载班次配置
            LoadShiftConfig();
            // 设置当前班次（确保始终有效）
            currentShift = DetermineCurrentShift(DateTime.Now);
            previousShift = currentShift;

            // 启动计时器
            unifiedStopwatch.Start();
            statusTimer.Start();
            idleTimer.Start(); // 启动空闲检测
                               // 启动刷新定时器
            refreshTimer.Start();


            // 设置点检记录检查定时器
            //checkRecordTimer.Start();
            //ScheduleCheckRecordTimer();
            // 设置初始化完成标志
            isInitialized = true;
            currentStatus = DeviceStatus.Error;
        }

        private void ScheduleCheckRecordTimer()
        {
            DateTime now = DateTime.Now;
            DateTime eightAM = now.Date.AddHours(8); // 今天早上8点

            // 如果已经过了今天8点，则设置到明天8点
            if (now > eightAM)
            {
                eightAM = eightAM.AddDays(1);
            }

            // 计算距离早上8点还有多少毫秒
            int millisecondsUntilEightAM = (int)(eightAM - now).TotalMilliseconds;

            // 创建一个一次性定时器，在早上8点启动检查定时器
            System.Windows.Forms.Timer startTimer = new System.Windows.Forms.Timer();
            startTimer.Interval = millisecondsUntilEightAM;
            startTimer.Tick += (s, e) =>
            {
                // 启动检查定时器
                if (!hasDayCheckRecord && !isCheckTimerRunning)
                {
                    checkRecordTimer.Start();
                    isCheckTimerRunning = true;
                }

                // 停止并销毁这个一次性定时器
                startTimer.Stop();
                startTimer.Dispose();
            };
            startTimer.Start();
        }

        private void CheckRecordTimer_Tick(object sender, EventArgs e)
        {
            // 检查点检记录
            bool newHasDayCheckRecord = bts.GetDayData();

            // 如果状态有变化，更新UI
            if (newHasDayCheckRecord != hasDayCheckRecord)
            {
                hasDayCheckRecord = newHasDayCheckRecord;

                // 更新UI必须在UI线程上执行
                this.Invoke(new Action(() =>
                {
                    // 只在没有点检记录时设置浅蓝色背景
                    if (!hasDayCheckRecord)
                    {
                        topPanel.BackColor = Color.Blue;
                    }
                    else
                    {
                        topPanel.BackColor = Color.Empty; // 恢复默认颜色
                                                          // 停止定时器，因为已经检查到点检记录
                        checkRecordTimer.Stop();
                        isCheckTimerRunning = true;
                    }
                    topPanel.Invalidate(); // 强制重绘
                }));
            }
        }
        /// <summary>
        /// 加载读取点位信息
        /// </summary>
        private void LoadDeviceAddresses()
        {
            try
            {
                string filePath = "DeviceStatus.xml";
                if (!File.Exists(filePath))
                    throw new FileNotFoundException("状态文件未找到");

                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);

                // 读取状态点位
                XmlNode statusNode = doc.SelectSingleNode("/DeviceState/Status");
                statusAddress = statusNode?.InnerText ?? "D1";

                // 读取生产数据点位
                //XmlNode totalNode = doc.SelectSingleNode("/DeviceState/TotalCount");
                //totalCountAddress = totalNode?.InnerText ?? "D100";

                XmlNode okNode = doc.SelectSingleNode("/DeviceState/OKCount");
                okCountAddress = okNode?.InnerText ?? "D8000";

                XmlNode ngNode = doc.SelectSingleNode("/DeviceState/NGCount");
                ngCountAddress = ngNode?.InnerText ?? "D8006";
            }
            catch (Exception ex)
            {
                // 使用默认地址
                statusAddress = "D1";
                //totalCountAddress = "D100";
                okCountAddress = "D8000";
                ngCountAddress = "D8006";
                MessageBox.Show($"加载点位配置失败: {ex.Message}\n使用默认地址");
            }
        }
        /// <summary>
        /// 状态页定时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void StatusTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                // 1. 检查PLC连接状态
                // 2. 读取状态点位
                //var connectionResult = await CheckPLCConnectionAsync();
                //if (!connectionResult.IsSuccess)
                //{
                //    //throw new Exception(connectionResult.ErrorMessage);
                //    // PLC连接失败时不累计时间，只更新错误状态
                //    if (currentStatus != DeviceStatus.Error)
                //    {
                //        UpdateStatusUI(DeviceStatus.Error);
                //        lblStatus.Text = connectionResult.ErrorMessage;
                //        lblCurrentStatusDuration.Text = "通信错误";
                //        currentStatus = DeviceStatus.Error;
                //    }
                //    else
                //    {
                //        lblStatus.Text = "连接失败";
                //        lblCurrentStatusDuration.Text = "通信错误";
                //    }
                //    unifiedStopwatch.Restart(); // 重置计时器
                //    return;
                //}
                // 获取精确时间增量
                TimeSpan elapsed = unifiedStopwatch.Elapsed;
                unifiedStopwatch.Restart();
                // 3. 读取状态点位
                //var statusResult = await ReadDeviceValueAsync(statusAddress);
                //if (!statusResult.IsSuccess)
                //{
                //    throw new Exception(statusResult.ErrorMessage);
                //}
                // 1. 读取状态点位
                //int statusValue = await ReadDeviceValue(statusAddress);
                int statusValue = D1;
                DeviceStatus newStatus = DetermineStatus(statusValue);

                // 2. 更新状态和时间累计
                UpdateStatusAndTimes(newStatus, elapsed);

                // 3. 读取生产数据点位
                //totalCount = await ReadDeviceValue(totalCountAddress);
                //okCount = await ReadDeviceValue(okCountAddress);
                //ngCount = await ReadDeviceValue(ngCountAddress);
                okCount = D2;
                ngCount = D3;

                // 5. 读取生产数据点位
                //var okResult = await ReadDeviceValueAsync(okCountAddress);
                //if (!okResult.IsSuccess)
                //{
                //    okCount =0;
                //}
                //else
                //{
                //    okCount = okResult.Value.Value;
                //}
                //var ngResult = await ReadDeviceValueAsync(ngCountAddress);
                //if (!ngResult.IsSuccess)
                //{
                //    ngCount =0;
                //}
                //else
                //{
                //    ngCount = ngResult.Value.Value;
                //}
                // 4. 计算总数
                totalCount = okCount + ngCount; // 新增计算
                // 4. 更新生产数据到界面
                UpdateProductionData();
                // 5. 更新界面显示
                UpdateTimeDisplays();

                // 6. 检查班次变化
                CheckShiftChange();
                

            }
            catch (Exception ex)
            {
                // 仅在未处于错误状态时更新为错误状态
                if (currentStatus != DeviceStatus.Error)
                {
                    UpdateStatusUI(DeviceStatus.Error);
                    lblStatus.Text = $"{ex.Message}";
                    lblCurrentStatusDuration.Text = "通信错误";
                    currentStatus = DeviceStatus.Error;
                }
                else
                {
                    lblStatus.Text = $"{ex.Message}";
                    lblCurrentStatusDuration.Text = "通信错误";
                    currentStatus = DeviceStatus.Error;
                }
            }
        }

        // 异步检查PLC连接
        private async Task<PlcOperationResult> CheckPLCConnectionAsync()
        {
            return await Task.Run(() =>
            {
                try
                {
                    // 如果已经连接，直接返回成功
                    if (isPlcConnected)
                        return new PlcOperationResult(true);

                    // 尝试连接PLC
                    var connectResult = plcClient.ConnectServer();
                    if (!connectResult.IsSuccess)
                    {
                        return new PlcOperationResult(false, null, "PLC连接失败");
                    }
                    // 连接成功，设置标志
                    isPlcConnected = true;
                    return new PlcOperationResult(true);
                }
                catch (Exception ex)
                {
                    return new PlcOperationResult(false, null, $"PLC连接异常: {ex.Message}");
                }
            });
        }

        // 统一的PLC操作结果类
        public class PlcOperationResult
        {
            public bool IsSuccess { get; set; }
            public int? Value { get; set; }
            public string ErrorMessage { get; set; }

            public PlcOperationResult(bool isSuccess, int? value= null, string errorMessage = "")
            {
                IsSuccess = isSuccess;
                Value = value;
                ErrorMessage = errorMessage;
            }
        }
        private async Task<int> ReadDeviceValue(string address)
        {
            return await Task.Run(() =>
            {
                var result = plcClient.ReadInt16(address);
                return result.IsSuccess ? result.Content : 0;

                // 首先检查PLC连接状态
                //if (!plcClient.ConnectServer().IsSuccess)
                //{
                //    throw new Exception("PLC连接失败");
                //}

                //var result = plcClient.ReadInt16(address);
                //if (!result.IsSuccess)
                //{
                //    throw new Exception($"读取点位{address}失败: {result.Message}");
                //}
                //return result.Content;


            });
        }
        // 异步读取设备值
        private async Task<PlcOperationResult> ReadDeviceValueAsync(string address)
        {
            return await Task.Run(() =>
            {
                try
                {
                    // 先检查连接状态，如果之前标记为未连接，则直接返回失败
                    if (!isPlcConnected)
                    {
                        return new PlcOperationResult(false, null, "PLC连接已断开");
                    }

                    var result = plcClient.ReadInt16(address);
                    if (!result.IsSuccess)
                    {
                        // 连接成功，设置标志
                        isPlcConnected = true;
                        return new PlcOperationResult(false, null, $"读取点位{address}失败: {result.Message}");
                    }

                    return new PlcOperationResult(true, result.Content);
                }
                catch (Exception ex)
                {
                    // 连接成功，设置标志
                    isPlcConnected = true;
                    return new PlcOperationResult(false, null, $"读取点位{address}异常: {ex.Message}");
                }
            });
        }
        private DeviceStatus DetermineStatus(int? value)
        {
            if (value == 1) return DeviceStatus.Running;
            if (value == 3) return DeviceStatus.Alarm;
            if (value == 0) return DeviceStatus.Stop;
            return DeviceStatus.Error;
        }

        private void UpdateStatusAndTimes(DeviceStatus newStatus, TimeSpan elapsed)
        {
            // 添加强制更新标志：当前状态为错误且新状态不是错误（网络恢复）
            bool forceUpdate = (currentStatus == DeviceStatus.Error && newStatus != DeviceStatus.Error);
            // 状态变化处理
            if (forceUpdate || currentStatus != newStatus)
            {

                // 保存状态变更前的持续时间

                //lastStatusChange = DateTime.Now;
                //currentStatusStartTime = TimeSpan.Zero;

                currentStatus = newStatus;
                // 重置当前状态计时器（但保留时间余数）
                if (isInitialized && !isFirstStatusUpdate &&
                    newStatus != DeviceStatus.Error)
                {
                    SaveStatusToDatabase(previousShift.ToString());
                }

                // 更新UI状态
                UpdateStatusUI(newStatus);
                currentStatusStartTime = TimeSpan.Zero;
                currentStatusStartTime += elapsed;
                // 累计总时间（无论状态是否变化）
                switch (currentStatus)
                {
                    case DeviceStatus.Running: runningTime += elapsed; break;
                    case DeviceStatus.Alarm: alarmTime += elapsed; break;
                    case DeviceStatus.Stop: stopTime += elapsed; break;
                }
                isFirstStatusUpdate = false;
            }
            else
            {
                // 累计当前状态持续时间
                currentStatusStartTime += elapsed;
                // 累计总时间（无论状态是否变化）
                switch (currentStatus)
                {
                    case DeviceStatus.Running: runningTime += elapsed; break;
                    case DeviceStatus.Alarm: alarmTime += elapsed; break;
                    case DeviceStatus.Stop: stopTime += elapsed; break;
                }
            }
        }

        private void UpdateStatusUI(DeviceStatus status)
        {
            switch (status)
            {
                case DeviceStatus.Running:
                    tabPage1.BackColor = Color.LimeGreen;
                    lblStatus.Text = "运行";
                    break;
                case DeviceStatus.Alarm:
                    tabPage1.BackColor = Color.Red;
                    lblStatus.Text = "报警";
                    break;
                case DeviceStatus.Stop:
                    tabPage1.BackColor = Color.Yellow;
                    lblStatus.Text = "停机";
                    break;
                case DeviceStatus.Error:
                    tabPage1.BackColor = Color.Gray;
                    lblStatus.Text = "通信错误";
                    break;
            }
        }

        private void UpdateProductionData()
        {
            // 更新总数、OK数、NG数
            lblTotalCountValue.Text = totalCount.ToString();
            lblOkCountValue.Text = okCount.ToString();
            lblNgCountValue.Text = ngCount.ToString();

            // 计算并显示良率
            double yieldRate = 0.0;
            if (totalCount > 0)
            {
                yieldRate = (okCount * 100.0) / totalCount;
            }
            lblYieldRateValue.Text = $"{yieldRate:F2}%";
        }

        private void UpdateTimeDisplays()
        {
            // 更新运行、停机、报警时间
            lblRunningTime.Text = $"运行时长: {FormatTimeSpan(runningTime)}";
            lblStopTime.Text = $"停机时长: {FormatTimeSpan(stopTime)}";
            lblAlarmTime.Text = $"报警时长: {FormatTimeSpan(alarmTime)}";
            lblCurrentStatusDuration.Text = FormatTimeSpan1(currentStatusStartTime);
            // 更新当前状态持续时间
            if (currentStatus == DeviceStatus.Error)
            {
                lblCurrentStatusDuration.Text = "通信中断";
            }
        }

        private string FormatTimeSpan(TimeSpan ts)
        {
            return $"{(int)ts.TotalHours:D2}:{ts.Minutes:D2}:{ts.Seconds:D2}";
        }

        private string FormatTimeSpan1(TimeSpan ts)
        {
            //return $"{ts.Hours:D2}:{ts.Minutes:D2}:{ts.Seconds:D2}";
            return $"{(int)ts.TotalHours:D2}:{ts.Minutes:D2}:{ts.Seconds:D2}";
        }
        private void LoadShiftConfig()
        {
            try
            {
                string filePath = "ShiftConfig.xml";
                if (!File.Exists(filePath)) return;

                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);

                // 解析班次时间
                XmlNode dayNode = doc.SelectSingleNode("/Shifts/DayShift");
                XmlNode nightNode = doc.SelectSingleNode("/Shifts/NightShift");

                // 解析时间并存储为TimeSpan
                dayShiftStart = TimeSpan.Parse(dayNode.SelectSingleNode("StartTime").InnerText);
                dayShiftEnd = TimeSpan.Parse(dayNode.SelectSingleNode("EndTime").InnerText);
                nightShiftStart = TimeSpan.Parse(nightNode.SelectSingleNode("StartTime").InnerText);
                nightShiftEnd = TimeSpan.Parse(nightNode.SelectSingleNode("EndTime").InnerText);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载班次配置失败: {ex.Message}\n将使用默认班次设置");
            }
        }

        private bool CheckShiftChange()
        {
            DateTime now = DateTime.Now;
            ShiftType newShift = DetermineCurrentShift(now);

            if (newShift != currentShift)
            {
                // 记录班别切换日志
                LogShiftChange(previousShift, currentShift, newShift);
                // 保存旧班别数据
                SaveStatusToDatabase1(previousShift.ToString());

                currentShift = newShift;
                previousShift = currentShift;
                shiftChangeTime = now;

                // 重置所有计时器
                ResetAllTimes();
                return true;
            }
            return false;
        }
        /// <summary>
        /// 班别切换日志
        /// </summary>
        /// <param name="previous"></param>
        /// <param name="current"></param>
        /// <param name="newShift"></param>
        private void LogShiftChange(ShiftType previous, ShiftType current, ShiftType newShift)
        {
            string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - " +
                               $"班别变化: {GetShiftDisplayName(previous)} -> " +
                               $"{GetShiftDisplayName(newShift)}";

            // 写入日志文件或系统日志
            Debug.WriteLine(logMessage);

            // 可选：写入文件日志
            try
            {
                File.AppendAllText("shift_change.log", logMessage + Environment.NewLine);
            }
            catch
            {
                // 忽略日志写入错误
            }
        }
        /// <summary>
        /// 判断班别
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private ShiftType DetermineCurrentShift(DateTime time)
        {
            //TimeSpan currentTime = time.TimeOfDay;

            //// 判断白班是否跨天
            //bool isDayShiftCrossMidnight = dayShiftStart > dayShiftEnd;
            //bool isNightShiftCrossMidnight = nightShiftStart > nightShiftEnd;

            //// 处理白班跨天
            //if (isDayShiftCrossMidnight)
            //{
            //    if (currentTime >= dayShiftStart || currentTime < dayShiftEnd)
            //        return ShiftType.DayShift;
            //}
            //else
            //{
            //    if (currentTime >= dayShiftStart && currentTime < dayShiftEnd)
            //        return ShiftType.DayShift;
            //}

            //// 处理晚班跨天
            //if (isNightShiftCrossMidnight)
            //{
            //    if (currentTime >= nightShiftStart || currentTime < nightShiftEnd)
            //        return ShiftType.NightShift;
            //}
            //else
            //{
            //    if (currentTime >= nightShiftStart && currentTime < nightShiftEnd)
            //        return ShiftType.NightShift;
            //}

            //return currentShift;

            TimeSpan currentTime = time.TimeOfDay;

            // 处理白班（08:00-20:00）
            if (currentTime >= dayShiftStart && currentTime < dayShiftEnd)
                return ShiftType.DayShift;

            // 处理晚班（20:00-08:00，跨天）
            // 当前时间在20:00-23:59:59之间，或者在00:00-08:00之间
            if (currentTime >= nightShiftStart || currentTime < nightShiftEnd)
                return ShiftType.NightShift;

            // 默认返回当前班别（理论上不会执行到这里）
            return currentShift;
        }

        private void SaveStatusToDatabase(string shiftType)
        {
            try
            {
                if (!isInitialized) return;

                MachineStatusMessage data = new MachineStatusMessage
                {
                    MachineId = MachindNo,
                    RunningTime = FormatTimeSpan(runningTime),
                    AlarmTime = FormatTimeSpan(alarmTime),
                    StopTime = FormatTimeSpan(stopTime),
                    AlarmMessage = "",
                    //TeamGroup = !string.IsNullOrEmpty(shiftType)
                    //    ? GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType))
                    //    : GetShiftDisplayName(currentShift),
                    TeamGroup = GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType)),
                    OkQty = okCount,
                    NgQty = ngCount,
                    GetTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };

                BContentToSqlServer bts = new BContentToSqlServer();
                bts.InsertMachineStatusTime(data);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"保存数据失败: {ex.Message}");
            }
        }

        private void SaveStatusToDatabase1(string shiftType)
        {
            try
            {
                if (!isInitialized) return;

                MachineStatusMessage data = new MachineStatusMessage
                {
                    MachineId = MachindNo,
                    RunningTime = FormatTimeSpan(runningTime),
                    AlarmTime = FormatTimeSpan(alarmTime),
                    StopTime = FormatTimeSpan(stopTime),
                    AlarmMessage = "班别切换",
                    //TeamGroup = !string.IsNullOrEmpty(shiftType)
                    //    ? GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType))
                    //    : GetShiftDisplayName(currentShift),
                    TeamGroup = GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType)),
                    OkQty = okCount,
                    NgQty = ngCount,
                    GetTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };

                BContentToSqlServer bts = new BContentToSqlServer();
                bts.InsertMachineStatusTime(data);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"保存数据失败: {ex.Message}");
            }
        }
        private string GetShiftDisplayName(ShiftType shift)
        {
            //switch (shift)
            //{
            //    case ShiftType.DayShift: return "白班";
            //    case ShiftType.NightShift: return "晚班";
            //    default: return "未知";
            //}

            return shift == ShiftType.DayShift ? "白班" : "晚班";
        }

        private void ResetAllTimes()
        {
            runningTime = TimeSpan.Zero;
            alarmTime = TimeSpan.Zero;
            stopTime = TimeSpan.Zero;
            currentStatusStartTime = TimeSpan.Zero;
            lastStatusChangeTime = DateTime.Now;
            unifiedStopwatch.Restart();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            // 断开网络连接
            //if (!string.IsNullOrEmpty(networkShareRoot))
            //{
            //    WNetCancelConnection2(networkShareRoot, 0, true);
            //}
            //// 如果不是由系统关机引起的关闭，则保存数据
            //if (e.CloseReason != CloseReason.WindowsShutDown............)
            //{
            //    SaveDataOnShutdown();
            //}
            try
            {
                // 保存最后状态数据
                //SaveStatusToDatabase();
                string shiftType = "";
                MachineStatusMessage data = new MachineStatusMessage
                {
                    MachineId = MachindNo, // 根据需要设置
                    RunningTime = FormatTimeSpan(runningTime),
                    AlarmTime = FormatTimeSpan(alarmTime),
                    StopTime = FormatTimeSpan(stopTime),
                    AlarmMessage = "程序关闭",//目前为空，后续添加
                    TeamGroup = !string.IsNullOrEmpty(shiftType)
                    ? GetShiftDisplayName((ShiftType)Enum.Parse(typeof(ShiftType), shiftType))
                    : GetShiftDisplayName(currentShift),
                    OkQty = okCount,
                    NgQty = ngCount,
                    //TeamGroup = "",
                    GetTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
                };

                bts.InsertMachineStatusTime(data);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"关闭时保存失败: {ex.Message}");
            }
            finally
            {
                statusTimer?.Stop();
                plcClient?.Dispose();
                base.OnFormClosing(e);
            }

            idleTimer?.Stop();
            idleTimer?.Dispose();
            // 停止刷新定时器
            refreshTimer?.Stop();
            refreshTimer?.Dispose();
            

            //// 停止和释放点检记录检查定时器
            //checkRecordTimer?.Stop();
            //checkRecordTimer?.Dispose();
            // 移除事件绑定
            this.MouseMove -= Form3_MouseMove;
            this.KeyDown -= Form3_KeyDown;
            // 解绑事件
            this.MouseClick -= Form3_MouseClick;
            this.ControlAdded -= Form3_ControlAdded;
            tabControl1.SelectedIndexChanged -= TabControl1_SelectedIndexChanged;

            // 移除应用程序域事件处理
            AppDomain.CurrentDomain.ProcessExit -= CurrentDomain_ProcessExit;
            AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;

            // 添加CEF关闭
            if (Cef.IsInitialized == true)
            {
                Cef.Shutdown();
            }
            base.OnFormClosing(e);
        }

        private void BindWorkOrdersToDataGridView(string machineId)
        {
            try
            {
                // 1. 从配置读取设备编码
                //string machineId = ConfigurationManager.AppSettings["DeviceCode"];
                dataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing;
                dataGridView1.ColumnHeadersHeight = 50;
                if (string.IsNullOrEmpty(machineId))
                {
                    MessageBox.Show("设备编码未配置！");
                    return;
                }

                // 2. 调用接口获取数据
                List<WorkNoList> workOrders = bts.GetWorkNo(machineId);

                // 3. 绑定到DataGridView
                if (workOrders != null && workOrders.Count > 0)
                {
                    // 配置列映射（字段名 -> 列名）
                    //dataGridView1.AutoGenerateColumns = false; // 禁止自动生成列
                    // 设置开始时间和结束时间列的格式
                    if (dataGridView1.Columns.Contains("Column5"))
                    {
                        dataGridView1.Columns["Column5"].DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss";
                        dataGridView1.Columns["Column5"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                    }
                    if (dataGridView1.Columns.Contains("Column6"))
                    {
                        dataGridView1.Columns["Column6"].DefaultCellStyle.Format = "yyyy-MM-dd HH:mm:ss";
                        dataGridView1.Columns["Column6"].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
                    }
                    // 绑定数据源
                    dataGridView1.DataSource = workOrders;

                    dataGridView1.RowTemplate.Height = 50;
                    Message.Text = "";
                }
                else
                {
                    //MessageBox.Show("未查询到工单数据");
                    Message.Text = "未查询到工单排程数据";
                    Message.ForeColor = Color.Red;
                }
            }
            catch (Exception ex)
            {
                //MessageBox.Show($"加载数据失败: {ex.Message}");
                Message.Text = $"加载数据失败: {ex.Message}";
                Message.ForeColor = Color.Red;
            }
        }

       
        //private void buttonSearch_Click(object sender, EventArgs e)
        //{
        //    string initialDirectory = EsopInitialDirectory;
        //    if (!Directory.Exists(initialDirectory))
        //    {
        //        MessageBox.Show($"无法访问路径：{initialDirectory}\n请检查网络连接或路径配置",
        //                        "路径错误",
        //                        MessageBoxButtons.OK,
        //                        MessageBoxIcon.Error);
        //        return;
        //    }

        //    OpenFileDialog openFileDialog = new OpenFileDialog();
        //    openFileDialog.InitialDirectory = initialDirectory;
        //    // 扩展过滤器：添加视频格式
        //    openFileDialog.Filter = "PDF文件|*.pdf|图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|视频文件|*.mp4;*.avi;*.wmv;*.mov;*.mkv|所有文件|*.*";
        //    openFileDialog.FilterIndex = 1;
        //    openFileDialog.RestoreDirectory = true;

        //    if (openFileDialog.ShowDialog() == DialogResult.OK)
        //    {
        //        panel_pdf.Controls.Clear();
        //        string filePath = openFileDialog.FileName;
        //        string fileExtension = Path.GetExtension(filePath).ToLower();

        //        // 根据文件类型选择播放方式
        //        if (IsVideoFile(fileExtension))
        //        {
        //            try
        //            {
        //                var player = new AxWMPLib.AxWindowsMediaPlayer();
        //                panel_pdf.Controls.Add(player);  // 先添加
        //                player.CreateControl();           // 再创建
        //                player.Dock = DockStyle.Fill;
        //                player.URL = filePath;
        //            }
        //            catch (Exception ex)
        //            {
        //                MessageBox.Show($"播放失败: {ex.Message}");
        //            }
        //            //// 使用Windows Media Player播放视频
        //            //var player = new AxWMPLib.AxWindowsMediaPlayer();
        //            //player.CreateControl();
        //            //player.Dock = DockStyle.Fill;
        //            //player.URL = filePath;
        //            //panel_pdf.Controls.Add(player);

        //        }
        //        else
        //        {
        //            // 使用ChromiumWebBrowser打开PDF/图片
        //            ChromiumWebBrowser browser = new ChromiumWebBrowser(filePath);
        //            browser.Dock = DockStyle.Fill;
        //            browser.MouseMove += Form3_MouseMove;
        //            browser.KeyDown += Form3_KeyDown;
        //            panel_pdf.Controls.Add(browser);
        //        }
        //    }
        //}

        //// 判断是否为视频文件
        //private bool IsVideoFile(string extension)
        //{
        //    string[] videoExtensions = { ".mp4", ".avi", ".wmv", ".mov", ".mkv" };
        //    return videoExtensions.Contains(extension);
        //}
        private void InitializeStatusTabLayout()
        {
            // 清除现有布局（保留控件）
            tabPage1.Controls.Clear();
            // 使用双缓冲面板
            // 主布局 - 100%空间
            DoubleBufferedTableLayoutPanel mainLayout = new DoubleBufferedTableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 1,
                RowCount = 3,
                Padding = new Padding(0),
                Margin = new Padding(0)
            };

            // 顶部面板占15%高度
            mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 15F));
            // 底部面板占85%高度
            mainLayout.RowStyles.Add(new RowStyle(SizeType.Percent, 85F));

            // 顶部面板 - 三个时间标签水平排列
            topPanel = new DoubleBufferedTableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 3,
                RowCount = 1,
                Margin = new Padding(0),
                //BackColor = Color.Blue,
                //Visible = true // 默认隐藏
            };
            topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33F));
            topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33F));
            topPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33F));

            // 添加时间标签到顶部面板
            lblRunningTime.Dock = DockStyle.Fill;
            lblRunningTime.TextAlign = ContentAlignment.MiddleCenter;
            lblStopTime.Dock = DockStyle.Fill;
            lblStopTime.TextAlign = ContentAlignment.MiddleCenter;
            lblAlarmTime.Dock = DockStyle.Fill;
            lblAlarmTime.TextAlign = ContentAlignment.MiddleCenter;

            topPanel.Controls.Add(lblRunningTime, 0, 0);
            topPanel.Controls.Add(lblStopTime, 1, 0);
            topPanel.Controls.Add(lblAlarmTime, 2, 0);

            // 底部面板 - 左右结构
            DoubleBufferedTableLayoutPanel bottomLayout = new DoubleBufferedTableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 2,
                RowCount = 1,
                Margin = new Padding(0)
            };
            bottomLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 66.66F)); // 左侧2/3
            bottomLayout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 33.33F)); // 右侧1/3

            // 左侧面板 - 状态和时间显示（垂直布局）
            DoubleBufferedTableLayoutPanel leftPanel = new DoubleBufferedTableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 1,
                RowCount = 3,
                Margin = new Padding(0)
            };
            leftPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 45F)); // 状态
            leftPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 10F)); // 持续时间
            leftPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 45F)); // 持续时间

            // 设置状态标签属性
            lblStatus.Dock = DockStyle.Fill;
            lblStatus.TextAlign = ContentAlignment.BottomCenter;
            lblStatus.AutoSize = false;
            lblStatus.Padding = new Padding(0, 0, 0, 20); // 增加底部内边距，使文本上移

            // 设置持续时间标签属性
            lblCurrentStatusDuration.Dock = DockStyle.Fill;
            lblCurrentStatusDuration.TextAlign = ContentAlignment.TopCenter;
            lblCurrentStatusDuration.AutoSize = false;
            lblCurrentStatusDuration.Padding = new Padding(0, 20, 0, 0); // 增加顶部内边距，使文本下移

            leftPanel.Controls.Add(lblStatus, 0, 0);
            leftPanel.Controls.Add(lblCurrentStatusDuration, 0, 2);

            // 右侧面板 - 生产信息（垂直布局）
            DoubleBufferedTableLayoutPanel rightPanel = new DoubleBufferedTableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 1,
                RowCount = 6,
                Margin = new Padding(0)
            };
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 10F)); // 间隔
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 20F)); // 总数
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 20F)); // OK数
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 20F)); // NG数
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 20F)); // 良率
            rightPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 10F)); // 间隔

            // 添加标签到右侧面板（每个标签占一行）
            AddLabelToPanel(rightPanel, lblTotalCount, lblTotalCountValue, 1);
            AddLabelToPanel(rightPanel, lblOkCount, lblOkCountValue, 2);
            AddLabelToPanel(rightPanel, lblNgCount, lblNgCountValue, 3);
            AddLabelToPanel(rightPanel, lblYieldRate, lblYieldRateValue, 4);

            // 将左右面板添加到底部布局
            bottomLayout.Controls.Add(leftPanel, 0, 0);
            bottomLayout.Controls.Add(rightPanel, 1, 0);

            // 将顶部和底部添加到主布局
            mainLayout.Controls.Add(topPanel, 0, 0);
            mainLayout.Controls.Add(bottomLayout, 0, 1);

            // 将主布局添加到tabPage1
            tabPage1.Controls.Add(mainLayout);

            // 设置初始字体大小
            AdjustStatusTabFontSizes();

            // 添加调整字体大小的处理
            //tabPage1.Resize += (s, e) => AdjustStatusTabFontSizes();

            // 设置初始背景色
            tabPage1.BackColor = Color.Gray;
        }

        // 辅助方法：将标签添加到面板
        private void AddLabelToPanel(TableLayoutPanel panel, Label title, Label value, int row)
        {
            TableLayoutPanel rowPanel = new TableLayoutPanel
            {
                Dock = DockStyle.Fill,
                ColumnCount = 2,
                RowCount = 1,
                Margin = new Padding(0)
            };
            rowPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
            rowPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 60F));

            title.Dock = DockStyle.Fill;
            title.TextAlign = ContentAlignment.MiddleRight;
            value.Dock = DockStyle.Fill;
            value.TextAlign = ContentAlignment.MiddleLeft;

            rowPanel.Controls.Add(title, 0, 0);
            rowPanel.Controls.Add(value, 1, 0);

            panel.Controls.Add(rowPanel, 0, row);
        }

        // 调整状态标签页的字体大小
        private void AdjustStatusTabFontSizes()
        {
            if (tabPage1.Controls.Count == 0 || !(tabPage1.Controls[0] is TableLayoutPanel mainLayout))
                return;

            // 获取顶部面板
            if (mainLayout.Controls.Count < 1 || !(mainLayout.Controls[0] is TableLayoutPanel topPanel))
                return;

            // 获取底部面板
            if (mainLayout.Controls.Count < 2 || !(mainLayout.Controls[1] is TableLayoutPanel bottomLayout))
                return;

            // 获取左侧面板
            if (bottomLayout.Controls.Count < 1 || !(bottomLayout.Controls[0] is TableLayoutPanel leftPanel))
                return;

            // 获取右侧面板
            if (bottomLayout.Controls.Count < 2 || !(bottomLayout.Controls[1] is TableLayoutPanel rightPanel))
                return;

            // 1. 调整顶部时间标签的字体大小
            float topFontSize = topPanel.Height * 0.4f;
            topFontSize = Math.Min(topFontSize, 48); // 最大限制
            topFontSize = Math.Max(topFontSize, 12); // 最小限制

            lblRunningTime.Font = new Font("宋体", topFontSize, FontStyle.Bold);
            lblStopTime.Font = new Font("宋体", topFontSize, FontStyle.Bold);
            lblAlarmTime.Font = new Font("宋体", topFontSize, FontStyle.Bold);

            // 2. 调整状态标签字体大小
            float statusFontSize = leftPanel.GetControlFromPosition(0, 0).Height * 0.5f;
            statusFontSize = Math.Min(statusFontSize, 180);
            lblStatus.Font = new Font("宋体", statusFontSize, FontStyle.Bold);

            // 3. 调整持续时间标签字体大小
            float durationFontSize = leftPanel.GetControlFromPosition(0, 2).Height * 0.5f;
            durationFontSize = Math.Min(durationFontSize, 200);
            lblCurrentStatusDuration.Font = new Font("宋体", durationFontSize, FontStyle.Bold);

            // 4. 调整右侧信息标签字体大小
            float infoFontSize = rightPanel.Height * 0.4f;
            infoFontSize = Math.Min(infoFontSize, 58);

            Font infoFont = new Font("宋体", infoFontSize, FontStyle.Bold);
            lblTotalCount.Font = infoFont;
            lblOkCount.Font = infoFont;
            lblNgCount.Font = infoFont;
            lblYieldRate.Font = infoFont;
            lblTotalCountValue.Font = infoFont;
            lblOkCountValue.Font = infoFont;
            lblNgCountValue.Font = infoFont;
            lblYieldRateValue.Font = infoFont;

            // 设置状态标签的底部内边距，使其文本上移
            int bottomPadding = (int)(lblStatus.Height * 0.10);
            lblStatus.Padding = new Padding(0, 0, 0, bottomPadding);
        }


        // 双缓冲TableLayoutPanel实现
        public class DoubleBufferedTableLayoutPanel : TableLayoutPanel
        {
            public DoubleBufferedTableLayoutPanel()
            {
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                              ControlStyles.AllPaintingInWmPaint |
                              ControlStyles.UserPaint, true);
                this.UpdateStyles();
            }
        }

        // 双缓冲Label实现
        public class DoubleBufferedLabel : Label
        {
            public DoubleBufferedLabel()
            {
                this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                             ControlStyles.AllPaintingInWmPaint |
                             ControlStyles.UserPaint, true);
                this.UpdateStyles();
            }
        }
        
        private void AttachIdleEventsToControls(Control control)
        {
            control.MouseMove += Form3_MouseMove;
            control.MouseClick += Form3_MouseClick; // 新增触摸事件
            control.KeyDown += Form3_KeyDown;

            // 递归绑定子控件
            foreach (Control child in control.Controls)
            {
                AttachIdleEventsToControls(child);
            }
        }
        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            AttachIdleEventsToControls(this); // 使用统一方法绑定
            tabControl1.SelectedIndexChanged += TabControl1_SelectedIndexChanged;
        }


        private void Form3_MouseMove(object sender, MouseEventArgs e)
        {
            ResetIdleTimer();
        }

        private void Form3_KeyDown(object sender, KeyEventArgs e)
        {
            ResetIdleTimer();
        }

        private void TabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ResetIdleTimer();
        }
        // 处理触摸屏点击事件
        private void Form3_MouseClick(object sender, MouseEventArgs e)
        {
            ResetIdleTimer();
        }

        // 处理动态添加控件的事件绑定
        private void Form3_ControlAdded(object sender, ControlEventArgs e)
        {
            AttachIdleEventsToControls(e.Control);
        }
        private void ResetIdleTimer()
        {
            idleTimer.Stop();
            idleTimer.Start();
        }
        // 响应式字体调整
        private void MainForm_Resize(object sender, EventArgs e)
        {

        }


        private void tabPage1_Click(object sender, EventArgs e)
        {

        }




    }
}
